#include "Playlist.h"

using namespace std;

/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::Playlist
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--	PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      Playlist::Playlist()
--
--	RETURNS:		
--
--	NOTES:
--		default constructor for playlist
---------------------------------------------------------------------------------------*/
Playlist::Playlist() : playlist(), playing(0)
{
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::addSong
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--	PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      void addSong(Song s)
--                          Song s - the song to add to the playlist
--
--	RETURNS:		
--
--	NOTES:
--		adds a song to the playlist. If the song is already in the playlist it will not
--		add another instance of it, however it will set the votes to whatever the votes
--		in that song are.
---------------------------------------------------------------------------------------*/
void Playlist::addSong(Song * s)
{
    //check to make sure song does not already exist in playlist
    list<Song *>::iterator it;

    for (it = playlist.begin(); it != playlist.end(); it++)
    {
        if ((*it)->getFilename() == s->getFilename())
        {
            //we still want to set the votes even if it is in playlist
            (*it)->setVotes(s->getVotes());
            notifyAll(VotesChanged);
            return;
        }
    }

    playlist.push_back(s);
    notifyAll(SongAdded);
}
/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::removeSong
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--	PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      int removeSong(string filename)
--						string filename - the filename of the song to remove
--
--	RETURNS:		int: -1 on fail 0 on success	
--
--	NOTES:
--		removes a song from the playlist
---------------------------------------------------------------------------------------*/
bool Playlist::removeSong(string filename)
{
    list<Song *>::iterator it;

    for (it = playlist.begin(); it != playlist.end(); it++)
    {
        if ((*it)->getFilename() == filename)
        {
            playlist.erase(it);
            notifyAll(SongRemoved);
            return true;
        }
    }

    return false;
}
/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::voteSong
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--	PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      int removeSong(string filename)
--				string filename - the filename of the song to vote for
--
--	RETURNS:		int: -1 on fail 0 on success	
--
--	NOTES:
--		votes for a song in the playlist
---------------------------------------------------------------------------------------*/
bool Playlist::voteSong(string filename)
{
    list<Song *>::iterator it;

    for (it = playlist.begin(); it != playlist.end(); it++)
    {
        if ((*it)->getFilename() == filename)
        {
            (*it)->vote();
            notifyAll(VotesChanged);
            return true;
        }
    }

    return false;
}

Song * Playlist::getMostVoted ()
{
    list<Song *>::iterator it;
    Song * mostVoted = 0;

    if (playlist.empty())
        return 0;

   mostVoted = *(playlist.begin());

    for (it = playlist.begin(); it != playlist.end(); it++)
    {
        if ((*it)->getVotes() > mostVoted->getVotes())
            mostVoted = *it;
    }

    return mostVoted;
}

bool Playlist::hasNext ()
{
    if (getMostVoted() != 0)
        return true;

    return false;
}

Song * Playlist::next ()
{
    if (playing != 0)
    {
        playing->setVotes(0);
        notifyAll(VotesChanged);
    }

	Song * nextSong = getMostVoted();

    if (nextSong != 0)
    {
        setPlaying(nextSong);
    }

    return nextSong;
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::getMostVotesSong
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--      PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      string getMostVotesSong()
--
--	RETURNS:		string - filename of the song with the most votes
--
--	NOTES:
--		This song will return the song with the most votes in the playlist. If there are songs
--		that have equal numbers of votes it will return the first one found.
---------------------------------------------------------------------------------------*/
string Playlist::getMostVotesSong()
{
    string highestFilename = "No Song Found";
    Song * mostVoted = getMostVoted();

    if (mostVoted != 0)
        return mostVoted->getFilename();

    return highestFilename;
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::setPlaying
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--	PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      void setPlaying(Song s)
--						Song s - the currently playing song
--
--	RETURNS:		void	
--
--	NOTES:
--		sets the currently playing song.
---------------------------------------------------------------------------------------*/
void Playlist::setPlaying(Song * s)
{
    playing = s;
    notifyAll(NowPlayingChanged);
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::getPlaying
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--	PROGRAMMER:		Brad Paugh
--
--  INTERFACE:      Song getPlaying()
--
--	RETURNS:    Song - The currently playing song
--
--	NOTES:
--		gets the currently playing song.
---------------------------------------------------------------------------------------*/
Song * Playlist::getPlaying()
{
    return playing;
}

Song * Playlist::getSong(string filename)
{
	list<Song *>::iterator it;

    for (it = playlist.begin(); it != playlist.end(); it++)
    {
        if ((*it)->getFilename() == filename)
        {
            return *it;
        }
    }
    return 0;
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::copySongList
--
--	DATE:			March 27, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Erick Ribeiro
--
--	PROGRAMMER:		Erick Ribeiro
--
--      INTERFACE:      std::list<Song> copySongList ()
--
--	RETURNS:        std::list<Song> - List of Song objects.
--
--	NOTES:
--		gets the currently playing song.
---------------------------------------------------------------------------------------*/
std::list<Song *> Playlist::copySongList ()
{
    return playlist;
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	Playlist::parseToString
--
--	DATE:			March 22, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		Brad Paugh
--
--	PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      string parseToString()
--
--	RETURNS:		string - parsed string of all songs/votes
--
--	NOTES:
--		parses all the songs and votes in the playlist into a single string delimited by
--		the ETX character '\3'. This is so we can send the data across to the client.
--		returned string/packet will have the form
--
--		FILENAME\3VOTES\3FILENAME\3VOTES\3....and so on
---------------------------------------------------------------------------------------*/
string Playlist::parseToString()
{
    string listString = "";
    string s;
    ostringstream oss;
    list<Song *>::iterator it;

    if ((this->getPlaying()) == 0)
        oss << "0\3";
    else
	oss << this->getPlaying()->getFilename() << "\3";
    for (it = playlist.begin(); it != playlist.end(); it++)
    {
        //delimited by ETX (\3)
        oss << (*it)->getFilename() << "\3" << (*it)->getVotes() << "\3";
        listString.append(oss.str());
        //clear string stream
        oss.str(string());
    }

    return listString;
}
